package engine;

import java.awt.*;
import java.util.logging.Logger;

/**
 * Object of this class is created when predator find his victim and hunting begin.
 * Created by kbarzilo on 26.07.2014.
 */
public class Hunting {

    private static Logger log = Logger.getLogger(Hunting.class.getName());

    public static final int TIRED_COEF = 10000;
    private final Cell cell;
    private final Creature hunter;
    private final Creature victim;

    public Hunting(Cell cell, Creature hunter, Creature victim) {
        this.cell = cell;
        this.hunter = hunter;
        this.victim = victim;
    }

    public static int colorDiff(Color c1, Color c2) {
        return Math.abs(c1.getRed() - c2.getRed()) + Math.abs(c1.getGreen() - c2.getGreen()) + Math.abs(c1.getBlue() - c2.getBlue());
    }

    public boolean start() {

        if (chase()) {
            cell.myWorld.shLog.append("\nChase of ").append(hunter).append(" on ").append(victim).append(" was successful");
            log.info("Chase of " + hunter + " on " + victim + " was successful");
            return fight();
        } else {
            cell.myWorld.shLog.append("\nChase of ").append(hunter).append(" on ").append(victim).append(" was failed");
            log.info("Chase of " + hunter + " on " + victim + " was failed");
            return false;
        }
    }

    private boolean chase() {
        int dist = Cell.CELL_SIZE / cell.creaturesOfCell.size();
        boolean victimGiveUp = false;
        boolean hunterGiveUp = false;
        int distDiff;
        while (dist > 0 && !victimGiveUp && !hunterGiveUp) {
            distDiff = 0;
            if (hunter.lookForCreature(victim, (int) (dist * 0.8f))) {
                distDiff -= hunter.run();
                //cell.myWorld.shLog.append("\nCreature ").append(hunter).append(" tired on ").append(hunter.getEnergy());
                log.info("Creature " + hunter + " have energy " + hunter.getEnergy());
            } else {
                //cell.myWorld.shLog.append("\nCreature ").append(hunter).append(" lost victim");
                log.info("Creature " + hunter + " lost victim");
                return false;
            }
            if (victim.lookForCreature(hunter, (int) (dist * 0.8f))) {
                distDiff += victim.run();
                //cell.myWorld.shLog.append("\nCreature ").append(victim).append(" tired on ").append(victim.getEnergy());
                log.info("Creature  " + victim + " have energy " + victim.getEnergy());
            } else {
                cell.myWorld.shLog.append("\nCreature ").append(victim).append(" cant see hunter");
            }
            dist += distDiff;
            log.info("Creature  " + hunter + " run on " + victim + " and dist=" + dist);

            victimGiveUp = victim.giveUp(hunter, dist, true);
            hunterGiveUp = hunter.giveUp(victim, dist, false);
        }
        if (hunterGiveUp) {
            return false;
        }
        if (dist > 0) {
            hunter.increaseEnergy(-dist * hunter.getWidth() / TIRED_COEF);
        }
        return true;
    }

    private boolean fight() {
        boolean hunterGiveUp = false;
        boolean victimAlive = true;
        boolean hunterAlive = true;
        while (!hunterGiveUp) {
            int hit = hunter.hit(victim);
            log.info("Hunter " + hunter + " damage " + victim + " on " + hit + ". " + victim.getHealth() + " health left");
            if (hit == 0) {
                hunterGiveUp = true;
            }
            if (victim.getHealth() <= 0) {
                log.info("Victim " + victim + " lose all health.");
                cell.myWorld.shLog.append("\nVictim ").append(victim).append(" lose all health.");
                victimAlive = false;
                break;
            }
            hit = victim.hit(hunter);
            log.info("Victim " + victim + " damage " + hunter + " on " + hit + ". " + hunter.getHealth() + " health left");
            if (hunter.getHealth() <= 0) {
                log.info("Hunter " + hunter + " lose all health.");
                cell.myWorld.shLog.append("\nHunter ").append(victim).append(" lose all health.");
                hunterAlive = false;
                break;
            }
            if ((hunter.getAttack() - hunter.looksLike(victim.getArmor()) <= 0)) {
                log.info("Hunters attack isn't enough.");
                cell.myWorld.shLog.append("\nHunters attack isn't enough.");
                hunterGiveUp = true;
            }
            if (hunter.looksLike(victim.getHealth()) / (long) Math.max((hunter.getAttack() - victim.getArmor()), 1) * hunter.getAttack() * hunter.getWidth() / hunter.getStamina() / Hunting.TIRED_COEF > hunter.getEnergy()) {
                log.info("Hunter have not enough energy for fight.");
                cell.myWorld.shLog.append("\nHunter have not enough energy for fight.");
                hunterGiveUp = true;
            }
        }

        if (!victimAlive) {
            victim.die("hunting");
            hunter.increaseHunger(-victim.getWidth());
            //cell.myWorld.shLog.append("\nHunting of ").append(hunter).append(" on ").append(victim).append(" was successful");
            log.info("Hunting of " + hunter + " on " + victim + " was successful");
            return true;
        }
        if (!hunterAlive) {
            hunter.die("hunting");
            cell.myWorld.shLog.append("\nHunting of ").append(hunter).append(" on ").append(victim).append(" was fatal");
            log.info("Hunting of " + hunter + " on " + victim + " was fatal");
            return false;
        }
        cell.myWorld.shLog.append("\nFight of ").append(hunter).append(" with ").append(victim).append(" was failed");
        log.info("Fight of " + hunter + " with " + victim + " was failed");
        return false;
    }
}
